package com.ruoyi.system.interceptor;


import com.ruoyi.common.utils.IPUtils;
import com.ruoyi.common.utils.RequestWrapper;
import com.ruoyi.system.domain.RequestLog;
import com.ruoyi.system.service.RequestLogService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.net.URLDecoder;
import java.time.LocalDateTime;


@Component
public class LoggingInterceptor implements HandlerInterceptor {
    @Autowired
    RequestLogService requestLogService;
    private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
    // 使用ThreadLocal来存储请求日志，以便在afterCompletion中访问
    private static final ThreadLocal<RequestLog> requestLogHolder = new ThreadLocal<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String queryString=null;
        String requestBody=null;
        //前端发的OPTIONS请求预见不做处理
        if(request.getMethod().toUpperCase().equals("OPTIONS")){
            return true;
        }
        //调整编码 获取请求参数
        if(StringUtils.isNotBlank(request.getQueryString())) {
            queryString = URLDecoder.decode(request.getQueryString(), "UTF-8");
        }
        //获取body参数 不能直接用request.getReader()获取，因为request.getReader()只能读取一次，controller第二次读取会报错
        //这里常采用包装类获取body参数
        RequestWrapper requestWrapper = new RequestWrapper(request);
        requestBody = requestWrapper.getBody();

        logger.info("Request IP:{},Request URL: {}, Method: {},query:{} ,body: {}", IPUtils.getIpAddr(request), request.getRequestURL(), request.getMethod(),queryString ,requestBody );
        //请求保存数据库
        RequestLog requestLog = new RequestLog(IPUtils.getIpAddr(request),request.getRequestURI(),request.getMethod(),requestBody,queryString, LocalDateTime.now());
        //set进日志线程
        requestLogHolder.set(requestLog);
        return true;
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        RequestLog requestLog = requestLogHolder.get();
        logger.info("Response Status: {}", response.getStatus());
        if(requestLog != null) {
            requestLog.setTimestampEnd(LocalDateTime.now());
            requestLog.setStatus(response.getStatus());
        }
        if (ex != null) {
            logger.error("Exception occurred: {}", ex.getMessage());
            requestLog.setException(ex.getMessage());
        }
        // 保存日志到数据库
        saveRequestLogAsync(requestLog);
        // 清除ThreadLocal变量
        requestLogHolder.remove();
    }
    // 异步保存日志到数据库的方法
    private void saveRequestLogAsync(RequestLog requestLog) {
        // 使用@Async注解、CompletableFuture或其他异步机制
        // 这里为了简单起见，使用新线程
        new Thread(() -> requestLogService.save(requestLog)).start();
    }


}
